/*
 * TowerPurpleOne.cs
 *
 * Created on December 14, 2007, 10:44 AM
 *
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 * Copyright (C) 2010       Mathijs Miermans
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace HexTD
{
	public class TowerBlueThree : TowerBase
	{

		public static int price = 5000000;
		public static int damage = 40;
		public static float range = 4f;

		private int fireAt = -1;
		private float enemyX = 0;
		private float enemyY = 0;
		private EnemySprite enemy;
		private COLOR damageColor = COLOR.BLUE;
		private int charge = 0;
		private int chargeMax = 40;

		private Color transColor;
#if PORT
		private Brush[] beam1Strokes;
		private Brush[] beam2Strokes;
		private Brush beam1Stroke;
		private Brush beam2Stroke;
#endif
		private Color beam1Color;
		private Color beam2Color;
#if PORT
		private Polygon[] pies;
#endif
		private Color line2Color;

		/** Creates a new instance of TowerRedOne */
		public TowerBlueThree(Game game, Context context, Hex hex)
			: base(game, TowerFactory.type.blueThree, price, damage, range)
		{
			this.lineColor = new Color(0xFF, 75, 75, 255);
			this.line2Color = new Color(0xFF, 25, 25, 128);
			this.transColor = new Color(100, this.lineColor.R, this.lineColor.G, this.lineColor.B);
			this.beam1Color = new Color(100, this.lineColor.R, this.lineColor.G, this.lineColor.B);
			this.beam2Color = new Color(0xFF, 139, 139, 255);
			this.doInit(context, hex);
		}

		public void doUpgrade()
		{
			this.level++;
			this.damageCurrent = (int)(this.damageBase * (1 + this.level) * (float)Math.Pow(1.05, this.level));
			this.calcDamageRange();
			this.fireTowerChangedEvent();
		}

		protected void calcDamageRange()
		{
#if PORT
			float lvl = (float)((1 + this.level) * (float)Math.Pow(1.05, this.level));
			float upg = (1f + 0.25f * this.upgradeDamage.Count);
			this.damageCurrent = (int)(this.damageBase * lvl * upg);
			this.damageText = "" + 0.1f * this.damageBase + "*" + lvl + "*" + upg + "=" + 0.1f * this.damageCurrent;

			lvl = (float)Math.Pow(1.07, this.level);
			upg = (1f + 0.25f * this.upgradeRange.Count);
			this.rangeCurrent = this.rangeBase * lvl * upg;
			this.rangeText = "" + this.rangeBase + "*" + lvl + "*" + upg + "=" + this.rangeCurrent;

			this.rangePaint = this.rangeCurrent * this.paintScale;
			this.rangeCurrent2 = this.rangeCurrent * this.rangeCurrent;
			this.rangeCircle = new EllipseGeometry();
			this.rangeCircle.Center = new Point(-rangePaint, -rangePaint);
			this.rangeCircle.RadiusX = rangePaint * 2;
			this.rangeCircle.RadiusY = rangePaint * 2;
#endif
		}

		public override void doTick(int gameTime)
		{
#if PORT
			if (this.charge == 0) {
				// Find a target
				int enemyNr = this.findEnemy(this.fireAt, true);
				this.fireAt = enemyNr;
				if (enemyNr >= 0) {
					this.charge++;
					this.enemy = this.context.enemies[enemyNr];
					this.enemyX = enemy.getX();
					this.enemyY = enemy.getY();
				}
			}
			if (this.charge > 0) {
				// Still a valid target?
				if (this.enemy.validTarget()) {
					this.charge++;
					if (this.charge >= this.chargeMax) {
						enemy.doDamage(1f*this.damageCurrent/10, sprite.DamageType.time, this.damageColor);
						this.charge=0;
					} else {
						this.beam1Stroke = this.beam1Strokes[this.charge-1];
						this.beam2Stroke = this.beam2Strokes[this.charge-1];
					}
				} else {
					this.charge = 0;
					this.enemy = null;
				}
			}
#endif
		}

		public override string getStatusString()
		{
			string retString = "";
			retString += "<h1>Blue Tower 1</h1>" +
					"<p>" +
					"<b>Level:</b> " + (1 + this.level) + "<br>\n" +
					"<b>Rewind:</b> " + this.damageText + "<br>\n" +
					"<b>Range:</b> " + this.rangeText + "<br>" +
					"<b>Refire rate:</b> 2/s" +
					"</p>\n";
			return retString;
		}

		public override string getInfoString()
		{
			string retString = "";
			retString += "<h1>Blue Tower 3</h1>" +
					"<p>" +
					"This tower generates a rift in the space-time continuum, causing it's target to be thrown back in time. " +
					"<br>Strong against blue enemies, very weak against yellow enemies." +
					"</p>" +
					"<p>" +
					"<b>Price:</b> " + price + "<br>" +
					"<b>Rewind:</b> " + 1f * this.damageCurrent / 10f + "<br>" +
					"<b>Range:</b> " + rangeCurrent + "<br>" +
					"<b>Refire rate:</b> 2/s" +
					"</p>";
			return retString;
		}

		protected override void generateShapes()
		{
#if PORT
			float width = this.context.hexPaintWidth;
			float scale2 = 0.5f*this.paintScale;
			int shapeCount = 2;
			int s;
        
        
			float[,] points2 = Geometry.createPolyCoords(this.paintScale);
			GeneralPath polyHex = Geometry.coordsToGeneralPath(points2, true);
        
			Area tower = new Area(polyHex);
        
			float[,] points1 = Geometry.createPolyCoords(scale2);
			polyHex = Geometry.coordsToGeneralPath(points1, true);
			Area tempArea = new Area(polyHex);
        
			tower.subtract(tempArea);
        
			GeneralPath poly = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
			poly.append(new LineSegment.Float(points2[0, 0], points2[0, 1], points2[2, 0], points2[2, 1]), true);
			poly.append(new LineSegment.Float(points2[2, 0], points2[2, 1], points2[4, 0], points2[4, 1]), true);
			poly.append(new LineSegment.Float(points2[4, 0], points2[4, 1], points2[0, 0], points2[0, 1]), true);
			poly.append(new LineSegment.Float(points2[1, 0], points2[1, 1], points2[3, 0], points2[3, 1]), false);
			poly.append(new LineSegment.Float(points2[3, 0], points2[3, 1], points2[5, 0], points2[5, 1]), true);
			poly.append(new LineSegment.Float(points2[5, 0], points2[5, 1], points2[1, 0], points2[1, 1]), true);
			tower.subtract(new Area(poly));

			s=0;
			this.shapes = new Shape[shapeCount];
			this.shapes[s++] = tower;
			this.shapes[s++] = new Ellipse.Float(-1.0f*this.context.strokeScale, -1.0f*this.context.strokeScale, 2.0f*this.context.strokeScale, 2.0f*this.context.strokeScale);
        
        
			this.strokes = new Brush[1];
			this.strokes[0] = new Brush(2.0f*this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
        
			float max = this.chargeMax;
			this.pies = new Shape[this.chargeMax+1];
			for (int i=0; i<this.pies.Length; i++) {
				this.pies[i] = new Arc2D.Float(-scale2, -scale2, scale2*2, scale2*2, 0, 360f*i/(max-1), Arc2D.PIE);
			}
        
			this.beam1Strokes = new Brush[this.chargeMax];
			this.beam2Strokes = new Brush[this.chargeMax];
			for (int i=0; i<this.chargeMax; i++) {
				this.beam1Strokes[i] = new Brush(6.0f* (float)i /max*this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
				this.beam2Strokes[i] = new Brush(3.0f* (float)i /max*this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
			}
#endif
		}

		public override void Draw(GameTime gameTime)
		{
#if PORT
			Brush defaultStroke = g2.getStroke();
			RotateTransform saveXform = g2.getTransform();
        
			g2.transform(atTranslate);
        
			g2.setColor(this.lineColor);
			g2.setStroke(this.strokes[0]);
			g2.fill(this.pies[this.charge]);
        
			g2.setColor(this.line2Color);
			g2.fill(this.shapes[0]);
        
			g2.setColor(this.lineColor);
			g2.draw(this.shapes[0]);
			g2.draw(this.shapes[1]);
        
			g2.setFont(this.levelFont);
			g2.drawString(""+(this.level+1), this.levelLocation[0], this.levelLocation[1]);
        
			if (this.selected) {
				g2.setColor(this.rangeColor);
				g2.draw(this.rangeCircle);
			}
        
			g2.setTransform(saveXform);
			g2.setStroke(defaultStroke);
#endif
		}

		public override void DrawEffects(GameTime gameTime)
		{
#if PORT
			Brush defaultStroke = g2.getStroke();
        
			if (this.fireAt > -1 && this.charge > 0) {
				float ex = this.enemy.getPaintX();
				float ey = this.enemy.getPaintY();
				g2.setColor(this.beam1Color);
				g2.setStroke(this.beam1Stroke);
				g2.draw(new LineSegment.Float(this.xPaint, this.yPaint, ex, ey));
				g2.setColor(this.beam2Color);
				g2.setStroke(this.beam2Stroke);
				g2.draw(new LineSegment.Float(this.xPaint, this.yPaint, ex, ey));
			}
        
			g2.setStroke(defaultStroke);
#endif
		}
	}
}